Skip to content

Test fix and sql support#24

Merged
CrazyBoyM merged 3 commits into
shareAI-lab:mainfrom
Gui-Yue:test_fix_and_sql_support
Jan 22, 2026
Merged

Test fix and sql support#24
CrazyBoyM merged 3 commits into
shareAI-lab:mainfrom
Gui-Yue:test_fix_and_sql_support

Conversation

@Gui-Yue

@Gui-Yue Gui-Yue commented Jan 21, 2026

Copy link
Copy Markdown
Contributor

PR: 添加 SQLite/PostgreSQL 持久化支持 & 资源清理与测试稳定性修复

概述

本 PR 包含三部分改动:

  1. 为 SDK 添加 SQLite 和 PostgreSQL 数据库持久化支持
  2. 修复子代理 sandbox 资源泄漏问题
  3. 修复多个测试稳定性问题

变更内容

  1. 数据持久化支持

新增依赖

  • better-sqlite3 - SQLite 数据库驱动
  • pg - PostgreSQL 数据库驱动

Store 模块重构

将原本 830 行的 src/infra/store.ts 拆分为模块化结构:
src/infra/
├── store.ts # 入口文件(向后兼容导出)
├── store/
│ ├── types.ts # 接口和类型定义
│ └── json-store.ts # JSONStore 文件存储实现
└── db/
├── sqlite/ # SQLite 实现
└── postgres/ # PostgreSQL 实现

CI 集成

  • 在 unit-tests job 中添加 PostgreSQL service container
  • 确保数据库相关单元测试在 CI 中自动执行
  1. 资源清理修复

Subagent Sandbox 泄漏修复 (src/core/agent.ts)

// Before: sandbox 未释放
const result = await subAgent.complete(config.prompt);
return result;

// After: 确保 sandbox 释放
try {
const result = await subAgent.complete(config.prompt);
return result;
} finally {
await (subAgent as any).sandbox?.dispose?.();
}

  1. 测试稳定性修复
    测试文件: agent-id.test.ts
    问题: 期望 agt: 但实际是 agt-
    修复方案: 修正为 agt- 并增加 Crockford Base32 验证
    ────────────────────────────────────────
    测试文件: agent.test.ts
    问题: CI 环境文件系统缓冲导致 resume 失败
    修复方案: 增加 50ms 延迟等待写入完成
    ────────────────────────────────────────
    测试文件: subagent.test.ts
    问题: prompt 不够明确导致断言不稳定
    修复方案: 优化 prompt 指令
    ────────────────────────────────────────
    测试文件: resume-flow.test.ts
    问题: 缺少 approval 处理
    修复方案: 增加权限请求自动处理
    ────────────────────────────────────────
    测试文件: room-collab.test.ts
    问题: 清理时资源未释放
    修复方案: 增加 sandbox dispose 和重试逻辑
    ────────────────────────────────────────
    测试文件: multi-provider.test.ts
    问题: 使用 Jest 语法
    修复方案: 重构为 SDK 的 TestRunner
  2. 配置清理
  • 移除 .env.test.example 中无用的 OPENAI_RESPONSES_* 配置
  • 移除 .github/workflows/ci.yml 中对应的环境变量

测试验证

  • npm run build 编译通过
  • npm run test:unit 单元测试通过 (181/181)
  • SQLite Store 测试通过 (19/19)
  • PostgreSQL Store 测试通过 (需要数据库环境)

破坏性变更

无。Store 模块保持完全向后兼容,现有导入路径无需修改。

  - Add better-sqlite3 and pg for database storage backends
  - Refactor store.ts into modular structure under store/ directory
  - Add PostgreSQL service to CI workflow for database tests
  - Fix agent-id test to validate agt- format with Crockford Base32
  - Fix integration test prompts and approval handling
  - Remove orphaned OPENAI_RESPONSES_* configurations
  - Dispose subagent sandbox after task_run completion
  - Add file system sync delay for resume test on CI
  - Improve test cleanup with retries and explicit sandbox disposal
@Gui-Yue

Gui-Yue commented Jan 21, 2026

Copy link
Copy Markdown
Contributor Author

Related: #1

@CrazyBoyM CrazyBoyM left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 PR #24 全面审查报告

基于对整个 Kode Agent SDK 架构、大规模部署场景、Serverless 兼容性的深度评估,对本 PR 进行全面审查。


一、PR 总体评价

评分: ⭐⭐⭐⭐ (4/5)

维度 评价
功能完整性 ✅ SQLite/PostgreSQL 双后端,QueryableStore 接口完善
架构设计 ✅ 混合存储策略合理,DB 存查询数据,FS 存高频写入
文档质量 ✅ 1000+ 行详细文档,示例丰富
向后兼容 ✅ Store 接口保持不变,现有代码无需修改
测试覆盖 ✅ 单元测试完整,CI 集成 PostgreSQL
代码质量 ⚠️ 存在需要修复的问题

结论: 功能设计优秀,建议修复高优先级问题后合并。


二、必须修复的问题 (Blocking)

2.1 PostgresStore 初始化状态检查缺失

位置: src/infra/db/postgres/postgres-store.ts

问题: 如果数据库连接失败,initPromise 会 reject,但后续调用 saveMessages() 等方法时没有检查初始化状态,可能导致静默失败或难以追踪的错误。

当前代码:

constructor(connectionConfig: any, fileStoreBaseDir: string) {
  this.pool = new Pool(connectionConfig);
  this.fileStore = new JSONStore(fileStoreBaseDir);
  this.initPromise = this.initialize().catch(err => {
    this.initError = err;
    throw err;  // 这里抛出但没有被处理
  });
}

建议修复:

private async ensureInitialized(): Promise<void> {
  await this.initPromise;
  if (this.initError) {
    throw new Error(`PostgresStore initialization failed: ${this.initError.message}`);
  }
}

async saveMessages(agentId: string, messages: Message[]): Promise<void> {
  await this.ensureInitialized();  // 每个公开方法都要加
  // ... 原有逻辑
}

2.2 connectionConfig 使用 any 类型

位置: src/infra/db/postgres/postgres-store.ts 构造函数

问题: 缺乏类型安全,错误的配置不会被编译期捕获。

建议修复 - 在 types.ts 中添加:

export interface PostgresConfig {
  host: string;
  port: number;
  database: string;
  user: string;
  password: string;
  ssl?: boolean | { rejectUnauthorized?: boolean };
  max?: number;                    // 连接池最大连接数
  idleTimeoutMillis?: number;      // 空闲连接超时
  connectionTimeoutMillis?: number; // 连接超时
}

三、强烈建议修复 (High Priority)

3.1 连接池默认配置与错误监听

建议改进:

constructor(config: PostgresConfig, fileStoreBaseDir: string) {
  const poolConfig = {
    ...config,
    max: config.max ?? 10,
    idleTimeoutMillis: config.idleTimeoutMillis ?? 30000,
    connectionTimeoutMillis: config.connectionTimeoutMillis ?? 5000,
  };
  
  this.pool = new Pool(poolConfig);
  
  // 监听连接池错误,避免未处理的异常
  this.pool.on('error', (err) => {
    console.error('[PostgresStore] Unexpected pool error:', err);
  });
  
  // ...
}

3.2 混合存储一致性风险

问题: 数据库写入成功但文件系统写入失败会导致状态不一致。

建议: 添加操作日志用于恢复判断(可在后续 PR 实现):

// 记录关键操作状态
interface OperationLog {
  id: string;
  agentId: string;
  operation: 'save_messages' | 'save_info' | 'fork';
  status: 'started' | 'db_committed' | 'fs_committed' | 'completed';
  startedAt: Date;
}

3.3 文档中 agentId 格式不一致

位置: docs/database.md

问题: 示例代码中仍使用旧的 agt: 格式,应统一为 agt-

- const messages = await store.queryMessages({ agentId: 'agt:abc123' });
+ const messages = await store.queryMessages({ agentId: 'agt-abc123' });

四、建议后续改进 (Follow-up)

4.1 健康检查接口

interface StoreHealthStatus {
  healthy: boolean;
  database: { connected: boolean; latencyMs?: number };
  fileSystem: { writable: boolean };
}

async healthCheck(): Promise<StoreHealthStatus>;

4.2 一致性检查接口

async checkConsistency(agentId: string): Promise<{
  consistent: boolean;
  issues: string[];
}>;

4.3 Store 工厂函数

function createStore(config: StoreConfig): Store {
  switch (config.type) {
    case 'json': return new JSONStore(config.baseDir);
    case 'sqlite': return new SqliteStore(config.dbPath);
    case 'postgres': return new PostgresStore(config);
  }
}

五、与 Issue #1 的关系

本 PR 正是 Issue #1 (云端数据库集成) 的解决方案。建议:

  1. PR 合并后,在 Issue #1 添加回复说明已通过 PostgresStore 解决
  2. 附带 docs/database.md 链接
  3. 关闭 Issue #1

六、大规模部署场景下的补充建议

基于对 Kode SDK 在大规模 To C 场景下的评估,建议在后续版本中考虑:

6.1 分布式锁支持

当多个 Worker 实例可能同时操作同一 Agent 时:

// PostgreSQL Advisory Lock
async acquireAgentLock(agentId: string): Promise<() => Promise<void>>;

6.2 批量操作优化

大量 Fork 场景下的性能优化:

async batchFork(agentId: string, count: number): Promise<string[]>;

6.3 指标采集

interface StoreMetrics {
  operations: { saves: number; loads: number; queries: number };
  performance: { avgLatencyMs: number };
  storage: { totalAgents: number; dbSizeBytes: number };
}

七、审查结论

检查项 状态
初始化状态检查 ❌ 需修复
类型定义 ❌ 需修复
连接池配置 ⚠️ 建议改进
文档一致性 ⚠️ 建议修复
功能完整性 ✅ 通过
测试覆盖 ✅ 通过
向后兼容 ✅ 通过

建议: 修复 2 个 blocking 问题后合并,其他问题可作为 follow-up。


八、Best Next Works 指南

阶段 1: 本 PR 修复 (合并前)

  • 添加 ensureInitialized() 检查到所有公开方法
  • 添加 PostgresConfig 类型定义
  • 添加连接池错误监听
  • 修复文档中的 agentId 格式

阶段 2: 紧随 PR (1-2 周内)

  • 添加 healthCheck() 方法
  • 添加 checkConsistency() 方法
  • 创建 createStore() 工厂函数
  • 在 Issue #1 添加回复并关闭

阶段 3: 后续迭代 (1-2 个月)

  • 实现分布式锁 (PostgreSQL Advisory Lock)
  • 添加 Store 指标采集
  • 评估 Redis Store 需求
  • 更新 README 添加适用场景说明

感谢 @Gui-Yue 的贡献!这是一个重要的功能增强,推进了 Kode SDK 的多实例部署和企业级应用。

@Gui-Yue

Gui-Yue commented Jan 22, 2026

Copy link
Copy Markdown
Contributor Author

✅ 二、必须修复的问题 (Blocking) - 已全部修复

2.1 PostgresStore 初始化状态检查

  • 添加 ensureInitialized() 私有方法
  • 在所有 17 个公开数据库方法开头调用
  • 添加 3 个初始化检测单元测试

2.2 connectionConfig 类型安全

  • 新增 PostgresConfig 接口(含完整 JSDoc 注释)
  • 构造函数参数类型 anyPostgresConfig

✅ 三、强烈建议修复 (High Priority) - 已全部修复

3.1 连接池默认配置与错误监听

const poolConfig = {
  ...config,
  port: config.port ?? 5432,
  max: config.max ?? 10,
  idleTimeoutMillis: config.idleTimeoutMillis ?? 30000,
  connectionTimeoutMillis: config.connectionTimeoutMillis ?? 5000,
};
this.pool.on('error', (err) => {
  console.error('[PostgresStore] Unexpected pool error:', err.message);
});

3.2 混合存储一致性风险

  • 已添加 checkConsistency() 方法用于检测一致性问题

3.3 文档 agentId 格式

  • 已修复 docs/database.md 中 4 处 agt:agt-
  • 同步修正测试文件中的格式

✅ 四、建议后续改进 (Follow-up) - 已提前实现

功能 状态 说明
healthCheck() 检查数据库连接 + 文件系统可写性
checkConsistency() 检测 DB 与 FS 数据一致性
createStore() 工厂函数 支持 json/sqlite/postgres 三种类型

✅ 六、大规模部署建议 - 已提前实现

功能 状态 说明
分布式锁 acquireAgentLock() PostgreSQL: Advisory Lock / SQLite: 内存锁
批量操作 batchFork() 事务内批量复制,支持大规模 Fork
指标采集 getMetrics() 操作计数 + 延迟统计 + 存储统计

📊 变更统计

  • +1159 行, -69 行
  • 新增测试: 7 个 (SqliteStore) + 3 个 (PostgresStore 初始化检测)
  • 总测试: 184 → 191,全部通过

📁 新增文件

  • src/infra/store/factory.ts - Store 工厂函数

🔄 七、审查结论更新

检查项 原状态 现状态
初始化状态检查
类型定义
连接池配置 ⚠️
文档一致性 ⚠️
健康检查接口 后续
一致性检查接口 后续
Store 工厂函数 后续
分布式锁 后续
批量操作 后续
指标采集 后续

…and distributed lock

  ## Blocking fixes
  - Add ensureInitialized() check to all PostgresStore public methods
  - Replace connectionConfig: any with typed PostgresConfig interface
  - Add connection pool default config and error listener

  ## New features (ExtendedStore interface)
  - healthCheck(): database and filesystem health status
  - checkConsistency(): verify data consistency between DB and filesystem
  - getMetrics(): operation counts, latency stats, storage stats
  - acquireAgentLock(): distributed lock (PostgreSQL advisory lock / memory lock)
  - batchFork(): optimized bulk agent forking

  ## Other changes
  - Add createStore() and createExtendedStore() factory functions
  - Fix agentId format in docs and tests (agt: → agt-)
  - Add comprehensive tests for new features
@Gui-Yue
Gui-Yue force-pushed the test_fix_and_sql_support branch from ab0fdfa to 19e3a22 Compare January 22, 2026 08:05
@Gui-Yue
Gui-Yue requested a review from CrazyBoyM January 22, 2026 13:18
@CrazyBoyM
CrazyBoyM merged commit 879963f into shareAI-lab:main Jan 22, 2026
7 checks passed
@Gui-Yue
Gui-Yue deleted the test_fix_and_sql_support branch February 9, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants